﻿using System;
using System.Collections.Generic;
using System.Management;

namespace FailoverClusterController
{
    /// <summary>
    /// Class que representa uma VM, e contem
    /// dados sobre a memoria que ela utiliza.
    /// </summary>
    public class VirtualMachine
    {
        public String name;
        public UInt64 memory;

        public VirtualMachine(String name, UInt64 memory)
        {
            this.name = name;
            this.memory = memory;
        }
    }

    /// <summary>
    /// Class que representa um node do Failover
    /// Cluster. Contem uma lista das VMs que estao
    /// rodando atualmente no seu sistema, alem de
    /// dados sobre a memoria total e a utilizada
    /// pelas maquinas virtuais.
    /// </summary>
    public class Host
    {
        public String name;
        public List<VirtualMachine> vms;
        public UInt64 usedMemory;
        public UInt64 totalMemory;

        public Host(String name)
        {
            this.name = name;
            this.vms = new List<VirtualMachine>();
            this.usedMemory = 0;
            this.totalMemory = calcTotalMemory();
        }

        // Adiciona uma VM a lista e atualiza a
        // memoria utilizada pelas maquinas virtuais.
        public void AddVM(VirtualMachine vm)
        {
            this.vms.Add(vm);
            this.usedMemory += vm.memory;
        }

        public void RemoveVM(VirtualMachine vm)
        {
            this.vms.Remove(vm);
            this.usedMemory -= vm.memory;
        }

        // Enconta a maquina virtual mais leve,
        // ou seja, a que tem menor memoria.
        public VirtualMachine getLightest()
        {
            if (vms.Count == 0)
            {
                return null;
            }

            int min = 0;
            for (int i = 1; i < vms.Count; i++)
            {
                if (vms[i].memory < vms[min].memory)
                    min = i;
            }

            return vms[min];
        }

        public Double usedMemRelative
        {
            get { return (double)usedMemory / (double)totalMemory; }
        }

        private ulong calcTotalMemory()
        {
            ulong total = 0;

            SelectQuery selectQuery = new SelectQuery("CIM_PhysicalMemory");
            ManagementObjectSearcher searcher =
                new ManagementObjectSearcher(selectQuery);

            foreach (ManagementObject mem in searcher.Get())
            {
                // retorna o total de memoria na VM em MB
                total += (ulong)mem["Capacity"] / 1048576;
            }

            return total;
        }
    }
}
